/**
 * 表示任务的数据负载类型。
 * 可根据实际需求调整此类型。
 */
type TaskData = any;

/**
 * 回调函数类型，用于处理任务执行后的行为。
 */
type TaskCallback = (data: TaskData, nextInvocation: Date) => void;

/**
 * 单个任务的接口定义。
 */
interface Task {
    /** 任务的唯一标识符。 */
    auto_import_id: string | symbol;
    /** 执行间隔时间（秒）。 */
    intervals: number;
    /** 任务的数据负载。 */
    data: TaskData;
}

/**
 * 自动导入任务管理器类。
 * 提供任务的添加、更新、删除及执行等功能。
 */
export default class AutoImportTask {
    private tasks: Map<string | symbol, {
        intervals: number;
        data: TaskData;
        intervalId: NodeJS.Timeout;
        nextInvocation: Date;
    }> = new Map();

    private callback: TaskCallback = (data: TaskData, nextInvocation: Date) => { };

    /**
     * 设置任务执行后的回调函数。
     * @param cb - 新的回调函数。
     */
    setCallBack(cb: TaskCallback): void {
        this.callback = cb;
    }

    /**
     * 添加或更新一个任务。
     * 如果任务已存在并且间隔时间没有改变，则只更新数据部分；
     * 否则，先移除旧任务再添加新任务。
     * @param task - 要添加或更新的任务对象。
     */
    addOrUpdateTask(task: Task): void {
        const { auto_import_id, intervals, data } = task;
        if (this.tasks.has(auto_import_id)) {
            const existingTask = this.tasks.get(auto_import_id)!;
            if (existingTask.intervals === intervals) {
                existingTask.data = data; // 直接更新数据
                return;
            } else {
                // 移除旧任务以更新间隔时间
                this.removeTask(auto_import_id);
            }
        }
        const newTask = {
            intervals,
            data,
            intervalId: setInterval(() => this.executeTask(auto_import_id), intervals * 1000),
            nextInvocation: new Date(Date.now() + intervals * 1000)
        };
        this.tasks.set(auto_import_id, newTask);
    }

    /**
     * 移除一个任务。
     * @param auto_import_id - 要移除的任务的唯一标识符。
     */
    removeTask(auto_import_id: string | symbol): void {
        const task = this.tasks.get(auto_import_id);
        if (task) {
            clearInterval(task.intervalId);
            this.tasks.delete(auto_import_id);
        }
    }

    /**
     * 执行一个任务。
     * @param auto_import_id - 要执行的任务的唯一标识符。
     */
    executeTask(auto_import_id: string | symbol): void {
        const task = this.tasks.get(auto_import_id);
        if (task) {
            console.log(`run [${String(auto_import_id)}] data:`, task.data);
            // 更新下次调用的时间
            task.nextInvocation = new Date(Date.now() + task.intervals * 1000);
            if (this.callback) {
                this.callback(task.data, task.nextInvocation);
            }
        }
    }

    /**
     * 查询单个任务的下一次执行时间。
     * @param auto_import_id - 要查询的任务的唯一标识符。
     * @returns 下次执行的时间，如果任务不存在则返回null。
     */
    queryNextInvocation(auto_import_id: string | symbol): Date | null {
        const task = this.tasks.get(auto_import_id);
        return task ? task.nextInvocation : null;
    }

    /**
     * 清理不在给定列表中的任务。
     * @param tasksList - 当前有效的任务列表。
     */
    cleanUp(tasksList: Task[]): void {
        const validIds = new Set(tasksList.map((task) => task.auto_import_id));
        for (const [id, task] of this.tasks) {
            if (!validIds.has(id)) {
                this.removeTask(id);
            }
        }
    }

    /**
     * 批量查询所有任务的下一次执行时间。
     * @returns 包含任务ID和下次执行时间的对象数组。
     */
    queryNextInvocations(): Array<{ auto_import_id: string | symbol, nextInvocations: Date }> {
        return Array.from(this.tasks.entries()).map(([auto_import_id, task]) => ({
            auto_import_id,
            nextInvocations: task.nextInvocation
        }));
    }
}